package com.zhongzhi.thread;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Timer;

import com.zhongzhi.bean.Configuration;
import com.zhongzhi.common.Common;
import com.zhongzhi.common.GrabDetail;
import com.zhongzhi.common.Plc;
import com.zhongzhi.common.Primary;
import com.zhongzhi.common.co;
import com.zhongzhi.springboot.pojo.EquipmentShow;
import com.zhongzhi.springboot.pojo.MeasureShow;
import com.zhongzhi.springboot.pojo.Station;
import com.zhongzhi.springboot.pojo.Type;
import com.zhongzhi.util.ClientUtil;
import com.zhongzhi.util.JsonResult;
import com.zhongzhi.util.PageUtil;

import javafx.application.Platform;
import javafx.event.EventHandler;
import javafx.scene.input.DataFormat;
import javafx.stage.Stage;
import javafx.stage.WindowEvent;
import lombok.Data;
import lombok.extern.log4j.Log4j;
/**
 * 测量线程
 * @author Administrator
 *
 */
@Data
@Log4j
public class TaskTherad extends Thread{

	private Integer stationid;	//工位id
	private String stationname;	//工位名
	private String type;		//机型
	private String num;			//机号

	private Long startTime;    	//开始时间
	private Long timeLong;		//运行时间
	private Boolean run = false;	//运行状态
	private Boolean stop = false;	//强行停止
	private Long resTime;		//剩余时间

	private Double startHA;		//初始高度A
	private Double curHA;		//当前高度A
	private Double disHA;		//下落距离A
	//	private Double stateA;		//预计下落A
	private String stateA;		//合格范围a

	private Double startHB;		//初始高度B
	private Double curHB;		//当前高度B
	private Double disHB;		//下落距离B
	//	private Double stateB;		//预计下落B
	private String stateB;		//合格范围b

	private Double upa;		//a上限
	private Double upb;		//b上限
	private Double downa;		//a下限
	private Double downb;		//b下限

	private Double excla;		//a排除
	private Double exclb;		//b排除

	private HashMap<Long, Double> mapaa = new HashMap<Long, Double>();
	private HashMap<Long, Double> mapbb = new HashMap<Long, Double>();
	/**
	 * 这个线程一直在循环运行,不过根据run变量的状态,来决定执不执行记录
	 * 如果run为true,则开始执行记录
	 * 1:首先记录开始时间
	 * 2:根据当前运行的工位id,得到工位信息,再根据工位信息,它所属的plc的信息
	 * 3:plc通道的数据存入了暂存信息内(其他类有这个功能),格局工位的通道,获取plc的通道里的数据,放入开始高度内
	 * 4:设置运行时间
	 * 5:设置结束时间
	 * 6:设置时间格式
	 * 7:此时检查程序是否被控制层设为关闭,如果设为关闭,则把run和stop设为false
	 * 8:如果当前时间小于结束时间,则等待300ms
	 * 9:将当前的测量数据同步到变量内,供其他程序调用
	 * 10:如果当前时间大于结束时间,则执行最后一次数据刷新,将数据存入数据库,再将循环完毕设为true
	 * 11:此时判断完毕后,程序跳到第七步判断,此时stop为true,执行语句,run为false,整个过程结束
	 */
	@Override
	public void run() {
		log.info("工位测试线程启动:"+this.getName());
		Station stationA =null;
		HashMap<Integer, Station> stationMapA = Common.getTaskStationMap();
		stationA = stationMapA.get(stationid);
		Integer equipmentIdA = stationA.getEquipmentId();
		PlcThread plcThreadA = Common.getPlcThread().get(equipmentIdA);
		if (plcThreadA!=null) {
			plcThreadA.getMap().put(stationA.getStationname(), "2");//1:运行,2:运行结束,3:报警
			//			System.out.println("task111"+plcThread.getMap().toString());
		}

		while (true) {


			if (run) {
				startTime = System.currentTimeMillis();
				timeLong = 1000L*60*5;
				Long endTime = startTime + timeLong;
				Station station =null;
				Plc plc = null;
				Date date = null;
				SimpleDateFormat format = Common.getFormat();
				PlcThread plcThread = null;
				
				int len = 60;							//采集数据次数
				double[] arraysa = new double[len];		//开始时采集数据a点
				double[] arraysb = new double[len];		//开始时采集数据b点
				double[] arrayea = new double[len];		//结束时采集数据a点
				double[] arrayeb = new double[len];		//结束时采集数据b点
				
				int numsa = 0;							//初始值采集次数a
				int numsb = 0;							//初始值采集次数b
				int numea = 0;							//结束值采集次数a
				int numeb = 0;							//结束值采集次数b
				boolean boola = false;					//初始采集完毕a
				boolean boolb = false;					//初始采集完毕b
				
				Double ha;			//未经加工的a
				Double hb;			//未经加工的b
				Double formerlya=0.0;			//过去的a
				Double formerlyb=0.0;			//过去的b
				
				int ref = 0;		//刷新频率
				
				try {
					log.info("工位测试"+this.getName()+"线程开始测试:"+stationname);
					HashMap<Integer, Station> stationMap = Common.getTaskStationMap();
					station = stationMap.get(stationid);
					Integer equipmentId = station.getEquipmentId();
					plc = Primary.getMap().get(equipmentId);
					
					date = new Date(startTime);

					//!发送消息给plc,让其亮灯
					plcThread = Common.getPlcThread().get(equipmentId);
					if (plcThread!=null) {
						plcThread.getMap().put(station.getStationname(), "1");//1:运行,2:运行结束,3:报警
					}

					formerlya = plc.getSjTemData().get(station.getNuma());			//过去的a
					formerlyb = plc.getSjTemData().get(station.getNumb());			//过去的b
					
					startHA = formerlya;
					curHA = formerlya;
					disHA=0.0;
					
					startHB = formerlyb;
					curHB = formerlyb;
					disHB=0.0;

				} catch (Exception e) {
					log.error("工位测试线程"+this.getName()+"初始化失败:"+e);
				}

				while (stop==false) {
					if (System.currentTimeMillis()<endTime) {
						try {
							Thread.sleep(500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						try {
							//数据处理
							ha = plc.getSjTemData().get(station.getNuma());
							ha = dispose(ha, formerlya);
							formerlya=ha;
							
							hb = plc.getSjTemData().get(station.getNumb());
							hb = dispose(hb, formerlyb);
							formerlyb=hb;
							
							//收集开始数据
							if (numsa<len) {
								arraysa[numsa] = ha;
								numsa++;
								
							}
							if (numsb<len) {
								arraysb[numsb] = hb;
								numsb++;
								
							}
							
							//收集实时(结束数据)
							arrayea[numea] = ha;
							numea++;
							if (numea>=len) {
								numea=0;
							}
							arrayeb[numeb] = hb;
							numeb++;
							if (numeb>=len) {
								numeb=0;
							}
							
							//判断开始收集数据是否结束
							if (numsa>=len) {
								if (boola==false) {				//只执行一次,使开始高度固定
									startHA = mean(arraysa);
									curHA = startHA;
									boola=true;
								}
							}
							if (numsb>=len) {
								if (boolb==false) {
									startHB = mean(arraysb);
									curHB = startHB;
									boolb=true;
								}
							}
							
							//判断刷新
							if (ref>=30 && boola && boolb) {
								System.out.println(ref);
								curHA = mean(arrayea);
								if (curHA>startHA) {
									curHA=startHA;
								}
								disHA = startHA - curHA;
								
								curHB = mean(arrayeb);
								if (curHB>startHB) {
									curHB=startHB;
								}
								disHB = startHB - curHB;
								disHB = mod(disHB-disHA)+disHA;				//补正
								ref = 0;
							}
							ref++;
							
							

							resTime = endTime-System.currentTimeMillis();
							stateA = doublebig(downa) + "~" + doublebig(upa);
							stateB = doublebig(downb) + "~" + doublebig(upb);

							date.setTime(startTime);
							String startT = format.format(date);
							Long i = resTime/1000;
							GrabDetail grabDetail = plc.getMap().get(stationid);
							grabDetail.setGrabDetail(type, num, startT, run, i.toString(), startHA.toString(), curHA.toString(), disHA.toString(), stateA.toString(), startHB.toString(), curHB.toString(), disHB.toString(), stateB.toString());
							plc.getMap().put(stationid, grabDetail);
						} catch (Exception e) {
						}

					}else {
						//10:
						try {

							run = false;
							date.setTime(System.currentTimeMillis());
							String startT = format.format(date);
							Long i = resTime/60/1000;
							GrabDetail grabDetail = plc.getMap().get(stationid);
							
							grabDetail.setGrabDetail(type, num, startT, run, i.toString(), startHA.toString(), curHA.toString(), disHA.toString(), stateA.toString(), startHB.toString(), curHB.toString(), disHB.toString(), stateB.toString());
						} catch (Exception e) {
							log.error("工位测试线程"+this.getName()+"同步画面出错:"+e);
						}
						
//						System.out.println(mapaa);
//						System.out.println(mapbb);
						
						//业务完毕,记录数据库
						String insert = insert();
						//11:循环完毕
						stop=true;
						run=false;

					}
				}
				//强制停止
				log.info("工位测试线程"+this.getName()+"测试结束:"+stationname);
				stop=false;
				run=false;


				//!发送消息给plc,让其亮灯
				if (plcThread!=null) {
					if((upa==null || upa==0)&&(downa==null || downa==0)&&(upb==null || upb==0)&&(downb==null || downb==0)) {
						plcThread.getMap().put(station.getStationname(), "2");//1:运行,2:运行结束,3:报警
					}else {
						//
						upa =-10.0;
						upb=-10.0;
						downa = -100.0;
						downb = -100.0;
						//如果ab下落距离都在范围内
						if (disHA>downa && disHA <upa&&disHB>downb && disHB <upb) {
							plcThread.getMap().put(station.getStationname(), "2");//1:运行,2:运行结束,3:报警
						}else {
							plcThread.getMap().put(station.getStationname(), "3");//1:运行,2:运行结束,3:报警
						}
					}
				}

			}
			try {
				Thread.sleep(150);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}

	//存储数据
	public String insert() {

		String returnstring = "存储数据成功";
		Integer id =0;

		try {
			//1:查询机型id
			String s="http://127.0.0.1:8080/type/selectByName?typeName="+type.trim();
			log.info("工位测试线程"+this.getName()+"查询机型id请求:"+s);
			String jsonhttp = ClientUtil.Gethttp(s);
			log.info("工位测试线程"+this.getName()+"查询机型id请求结果:"+jsonhttp);
			JsonResult jsonobj = ClientUtil.Jsonobj(jsonhttp, JsonResult.class);
			if (jsonobj.getCode()!=200) {
				returnstring = "存储测试信息时,根据机型查询机型id失败";
			}
			String typelistString = jsonobj.getData().toString();
			List<Type> jsonlist = ClientUtil.Jsonlist(typelistString, Type.class);
			id = jsonlist.get(0).getId();

		} catch (Exception e) {
			log.error("工位测试线程"+this.getName()+"查询机型id请求失败"+e);
			return null;
		}

		try {
			//根据机型和机号查询数据库
			String s2="http://127.0.0.1:8080/measure/selectByTypeNum?typeId="+id+"&deviceNum="+num;
			log.info("工位测试线程"+this.getName()+"根据机型和机号查询数据库:"+s2);
			String jsonhttp2 = ClientUtil.Gethttp(s2);
			log.info("工位测试线程"+this.getName()+"根据机型和机号查询数据库结果:"+jsonhttp2);
			JsonResult jsonobj2 = ClientUtil.Jsonobj(jsonhttp2, JsonResult.class);
			if (jsonobj2.getCode()!=200) {
				returnstring = "存储测试信息时,根据机号和机型查询数据失败";
			}
			String typelistString2 = jsonobj2.getData().toString();
			//如果数据不等于空,则删除原数据
			try {
				if (typelistString2!=null || typelistString2.equals("")==false) {
					List<MeasureShow> jsonlist2 = ClientUtil.Jsonlist(typelistString2, MeasureShow.class);
					String s3 = "http://127.0.0.1:8080/measure/deletenum?type="+type+"&num="+num;

					log.info("工位测试线程"+this.getName()+"根据机型和机号删除测试数据:"+s3);
					String jsonhttp3 = ClientUtil.Gethttp(s3);
					log.info("工位测试线程"+this.getName()+"根据机型和机号删除测试数据结果:"+jsonhttp3);
					JsonResult jsonobj3 = ClientUtil.Jsonobj(jsonhttp3, JsonResult.class);
					if (jsonobj3.getCode()!=200) {
						returnstring = "存储测试信息时,无法将数据库的数据删除";
					}
				}
			} catch (Exception e) {
				log.error("工位测试线程"+this.getName()+"根据机型和机号删除测试数据失败:"+e);
				return null;
			}

		} catch (Exception e) {
			log.error("工位测试线程"+this.getName()+"根据机型和机号查询数据库失败:"+e);
			return null;
		}

		try {
			//写入数据库
			if (disHA==null) {
				disHA=0.0;
			}
			if (startHA==null) {
				startHA=0.0;
			}
			if (disHB==null) {
				disHB=0.0;
			}
			if (startHB==null) {
				startHB=0.0;
			}

			String string="http://127.0.0.1:8080/measure/insertShow?deviceNum="+num.trim()
			+"&typeName="+type
			+"&startTime=" + startTime
			+"&endTime=" + System.currentTimeMillis()
			+"&stationId="+stationid
			+"&sinkA=" + disHA
			+"&startAltitudeA=" + startHA
			+"&sinkB=" + disHB
			+"&startAltitudeB=" + startHB
			+"&remark=" + "无";
			log.info("工位测试线程"+this.getName()+"新增测试数据:"+string);
			String jsonhttp3 = ClientUtil.Gethttp(string);
			log.info("工位测试线程"+this.getName()+"新增测试数据结果:"+jsonhttp3);
			JsonResult jsonobj3 = ClientUtil.Jsonobj(jsonhttp3, JsonResult.class);
			if (jsonobj3.getCode()!=200) {
				returnstring = "存储测试信息时,存储失败";
			}else {
				returnstring = "该信息已存入数据库";
			}
			return returnstring;
		} catch (Exception e) {
			log.error("工位测试线程"+this.getName()+"新增测试数据sb:"+e);
			return null;
		}

	}
	//四舍五入求近似值
	private double doublebig(double d) {
		BigDecimal daDecimal =new BigDecimal(new Double(d*0.1).toString());
		return daDecimal.setScale(1, RoundingMode.HALF_UP).doubleValue();
	}

	//去除最大最小,求平均数
	private double mean(double[] xx) {
		double[] xa = Arrays.copyOfRange(xx, 0,xx.length);
		Arrays.sort(xa);
		int i = xa.length*1/3;
		int j = xa.length*2/3;
		double[] copyOfRange = Arrays.copyOfRange(xa, i, j);
		double x = 0.0;
		for (double a : copyOfRange) {
			x=x+a;
		}
		return x/copyOfRange.length;
	}
	//B点补正
	private Double mod(Double d) {
		Configuration configuration = Common.getConfiguration();
		Double scope1=configuration.getScope1();
		Double scope2=configuration.getScope2();
		Double scope3=configuration.getScope3();
		Double scope4=configuration.getScope4();
		Double scope5=configuration.getScope5();
		Double scope6=configuration.getScope6();
		
		Double mod1=configuration.getMod1();
		Double mod2=configuration.getMod2();
		Double mod3=configuration.getMod3();
		Double mod4=configuration.getMod4();
		Double mod5=configuration.getMod5();
		Double mod6=configuration.getMod6();
		Double mod7=configuration.getMod7();
		
		if (d<=scope1) {
			return d*(1+mod1/100.0);
		}else if (d<=scope2 && d>scope1) {
			return d*(1+mod2/100.0);
		}else if (d<=scope3 && d>scope2) {
			return d*(1+mod3/100.0);
		}else if (d<=scope4 && d>scope3) {
			return d*(1+mod4/100.0);
		}else if (d<=scope5 && d>scope4) {
			return d*(1+mod5/100.0);
		}else if (d<=scope6 && d>scope5) {
			return d*(1+mod6/100.0);
		}else {
			return d*(1+mod7/100.0);
		}
	}
	//浮点数数据处理
	private Double dispose(Double d,Double formerly) {
		if (d==null) {
			return 0.0;
		}else if(d>=2450.0 || d<=50.0) {
			return formerly;
		}else {
			return d;
		}
		
	}

}
